#pragma once 
#include <boost/container_hash/hash.hpp>
#include <unordered_map>
#include <unordered_set>
#include "tinyrpc/base/coroutine/coroutine.h"
#include <atomic>
#include "eventloop.h"

#include <boost/functional/hash.hpp>
#include "tinyrpc/base/BlockingQueue.hpp"
namespace TinyRPC{


struct EventLoopAndCoroutine{
    EventLoop* eventloop;
    CoroutinePtr coroutine;

    EventLoopAndCoroutine(){}
    EventLoopAndCoroutine(EventLoop* loop, CoroutinePtr co){
        eventloop = loop;
        coroutine = co;
    }

    bool operator<(const EventLoopAndCoroutine& ec) const{
        if(eventloop == ec.eventloop){
            return coroutine < ec.coroutine;
        }else{
            return eventloop < ec.eventloop;
        }
    }

    bool operator==(const EventLoopAndCoroutine& ec) const{
        
        return coroutine.get() == ec.coroutine.get() && eventloop == ec.eventloop;
        
    }

    
};


// 自旋锁的实现
class SpinLock {
public:
    SpinLock() = default;
    SpinLock(const SpinLock&) = delete; 
    SpinLock& operator=(const SpinLock) = delete;
    void lock() {   // acquire spin lock
        while (flag.test_and_set()) {}
    }
    void unlock() {   // release spin lock
        flag.clear();
    }
private:
    std::atomic_flag flag;
};

void CoWakeUp(CoroutinePtr co);

#define UNLOCKED 1
#define LOCKED    0

//  1 unlock
//  0 lock
class CoLock{
public:
    CoLock()
    :m_val(UNLOCKED), m_next(nullptr){}

    void lock();
    void unlock();
private:
    std::atomic_int m_val;
    std::list<EventLoopAndCoroutine> m_waitList;
    CoroutinePtr m_next;
    SpinLock m_spinLock;
};




//  1 unlock
//  0 lock
class CoSem{
public:
    CoSem(int n):m_val(n){}

    void post();
    void wait();
private:
    std::atomic_int m_val;
    std::list<EventLoopAndCoroutine>  m_waitList;
    SpinLock m_spinLock;
};


template<typename LOCK>
class LockGuard{
public:
    LockGuard( LOCK& lock):m_lock(lock){
        m_lock.lock();
    }

    ~LockGuard(){
        m_lock.unlock();
    }
private:
    LOCK& m_lock;
    
};


}